package NG::Gen::Action::Search;
use strict;
use warnings;

use NG::Sys::Datetime;
use Data::Dumper;

sub new {
	my $class = shift;
	my %arg;
	if(ref $_[0]){
		%arg = %{$_[0]};
	}elsif(@_ % 2){
		die "odd number params\n";
	}else{
		%arg = @_;
	}
	unless($arg{app}){
		die "need app\n";
	}
	unless($arg{dbh}){
		die "need dbh\n";
	}
	my $self = bless \%arg,$class;
	$self->init;
	return $self;
}
sub init {
	my $self = shift;
	unless($self->{table}){
		die "need table";
	}
	unless($self->{pkey}){
		die "need pkey";
	}
	unless($self->{limit}){
		$self->{limit} = 100;
	}
	$self->{sth}{read} = $self->{dbh}->prepare("
		select `".$self->{pkey}."` from `".$self->{table}."` where
			`s_cat`=? and `can_attack`=1 and `can_search`=1
			order by `random`
			limit ".$self->{limit}
		);
	$self->{sth}{attack} = $self->{dbh}->prepare("
		update `".$self->{table}."`
			set `can_attack`=1
		where
			`can_attack`=0 and `last_attack` < ?
		");
	$self->{sth}{search} = $self->{dbh}->prepare("
		update `".$self->{table}."`
			set `can_search`=1
		where
			`can_search`=0 and `last_search` < ?
		");
	$self->{sth}{shuffle} = $self->{dbh}->prepare("
		update `".$self->{table}."`
			set `last_search`=?,`random`=`random`/2
		where
			`can_search`=1 and `last_search` < ?  and `random` > ?
		");
	$self->{sth}{shuffle2} = $self->{dbh}->prepare("
		update `".$self->{table}."`
			set `last_search`=?,`random`=`random` * ?
		where
			`can_search`=1 and `last_search` < ?
		");
	$self->{sth}{shuffle2r} = $self->{dbh}->prepare("
		select * from `".$self->{table}."`
		where
			`can_search`=1 and `last_search` < ?
		");
}
#!!! ВАЖНО возвращает залоченного юзера
sub search {
	my $self = shift;
	my $user_for = shift;
	my $sth = $self->{sth}{read};
	my $cat = $user_for->category;
	for(;;){
		$sth->execute($cat);
		my $list = $sth->fetchall_arrayref([]);
		unless(@$list){
			return 0;
		}
		while(@$list){
			my $row = splice @$list,rand(@$list),1;
			next if $user_for->obj_id == $row->[0];
			my $user = $self->{app}->users->get_by_id($row->[0]);
			$user->lock_get;
			$user->drop_context;
			if($user->can_attack && $user->can_search){
				$user->make_searched;
				return $user;
			}
			$user->lock_free;
		}
	}
	return 0;
}
sub check_attack {
	my $self = shift;
	my $tm = unixtime2timestamp(time() - $self->{app}->constant->attack_timeout);
	$self->{sth}{attack}->execute($tm);
}
sub check_search {
	my $self = shift;
	my $tm = unixtime2timestamp(time() - $self->{app}->constant->search_timeout);
	$self->{sth}{search}->execute($tm);
}
sub shuffle {
	my $self = shift;
	my $stm = unixtime2timestamp(time() - $self->{app}->constant->shuffle_timeout);
	my $utm = unixtime2timestamp(time() - $self->{app}->constant->search_timeout - 1);
	#$self->{sth}{shuffle}->execute($utm,$utm,$self->{app}->constant->shuffle_limit);

	$self->{sth}{shuffle2r}->execute($stm);
	my $list = $self->{sth}{shuffle2r}->fetchall_arrayref({});

	my $ret = $self->{sth}{shuffle2}->execute($utm,$self->{app}->constant->shuffle_limit,$stm);
	#$self->{app}->logger->info(sprintf "set=%s check=%s",ts2tm($utm),ts2tm($stm));
	#$self->{app}->logger->info(Dumper($list));
	return $ret;
}
sub ts2tm {
	my $ts = shift;
	return join(":",grep {$_}split /(\d{2})/,substr($ts,8));
}
1;
